package poker;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Vector;
import javax.swing.*;


public class Server extends Thread {
	private Vector<ServerConnection> clients;
	private ServerSocket server;
	private boolean openForConnections = true;
	Spel spel;
	private int dealerPointer = 0;
	private int smallBlindPointer = 0;
	private int bigBlindPointer = 0;
	String winMessage = "";
	String newWinMessage = "";
	
	Vector<ServerConnection> winnaars = new Vector<ServerConnection>();
	
	ServerConnection winnaar = null;
	
	public void syncAll() {
		ServerConnection c;
		Iterator<ServerConnection> i;
		i = clients.iterator();
		while(i.hasNext()){
			c = i.next();
			c.spel = spel;
			try {
				c.up();
			} catch (IOException e) { }
		}
	}
	
	public void resetAll()
	{
		ServerConnection c;
		Iterator<ServerConnection> i;
		i = clients.iterator();
		while(i.hasNext()){
			c = i.next();
			c.reset();
		}
	}
	
	public void run(){
		
		while(openForConnections){
			waitForAnother();
		}
		

		
		while(shouldGameContinue()){
			ServerConnection c;
			Iterator<ServerConnection> i;
			
			
			
			i = clients.iterator();
			while(i.hasNext()){
				c = i.next();
				c.deelname.isDealer = false;
				c.deelname.smallBlind = false;
				c.deelname.bigBlind = false;
			}
			


		
			spel.sr = new SpelRonde();
			
			winnaar = null;
			
			i = clients.iterator();
			Deelname d;
			while(i.hasNext()){
				d = i.next().deelname;
				spel.sr.deelnames.add(d);
				spel.sr.actieveSpelers++;
			}
			
			if(dealerPointer >= clients.size())
				dealerPointer = dealerPointer - clients.size();
			
			smallBlindPointer = dealerPointer + 1;
			if(smallBlindPointer >= clients.size())
				smallBlindPointer = smallBlindPointer - clients.size();
			bigBlindPointer = dealerPointer + 2;
			if(bigBlindPointer >= clients.size())
				bigBlindPointer = bigBlindPointer - clients.size();
			
			clients.get(dealerPointer).deelname.isDealer = true;
			clients.get(smallBlindPointer).deelname.smallBlind = true;
			clients.get(bigBlindPointer).deelname.bigBlind = true;
			

			dealerPointer++;
			
//			deel de kaarten.
			i = clients.iterator();
			while(i.hasNext()){
				c = i.next();
				c.spel = spel;
				Vector<Kaart> hand = new Vector<Kaart>();
				
				hand.add(spel.stapel.pakKaart());
				hand.add(spel.stapel.pakKaart());
				
				spel.sr.zoekDeelname(c.speler.spelerId).kaart = hand;
			}
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {}	
			syncAll();
			
			//post small en big blind
			i = clients.iterator();
			while(i.hasNext()){
				c = i.next();
				if(c.deelname.smallBlind)
				{
					c.spel = spel;
					try {
						c.up();
					} catch (IOException e) {}
					spel.sr.zoekDeelname(c.speler.spelerId).geefBeurt(true);
					c.spel = spel;
					try {
						c.up();
					} catch (IOException e) {}
					c.comment("Jij bent nu aan de beurt");
					c.down();
					spel = c.spel;
					spel.sr.zoekDeelname(c.speler.spelerId).geefBeurt(false);
					spel.serverMessage += spel.sr.zoekDeelname(c.speler.spelerId).speler.getNaam() + " posts the small blind";
					syncAll();
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {}
				}
			}
			i = clients.iterator();
			while(i.hasNext())
			{
				c = i.next();
				if(c.deelname.bigBlind)
				{
					c.spel = spel;
					try {
						c.up();
					} catch (IOException e) {}
					spel.sr.zoekDeelname(c.speler.spelerId).geefBeurt(true);
					c.spel = spel;
					try {
						c.up();
					} catch (IOException e) {}
					c.comment("Jij bent nu aan de beurt");
					c.down();
					spel = c.spel;
					spel.sr.zoekDeelname(c.speler.spelerId).geefBeurt(false);
					spel.serverMessage += "<br>" + spel.sr.zoekDeelname(c.speler.spelerId).speler.getNaam() + " posts the big blind";
					syncAll();
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {}
				}
			}
			
			while(winnaars.size() == 0)
			{
				
				inzetRonde();
							
				resetAll();
				
				//deel flop
				spel.sr.tafel[0] = spel.stapel.pakKaart();
				spel.sr.tafel[1] = spel.stapel.pakKaart();
				spel.sr.tafel[2] = spel.stapel.pakKaart();
				
				spel.serverMessage += "<br>Flop: " + spel.sr.tafel[0].getKrt() + ", " + spel.sr.tafel[1].getKrt() + ", " + spel.sr.tafel[2].getKrt();
				
				syncAll();
				
				
				inzetRonde();
				resetAll();
				
				//Deel turn
				spel.sr.tafel[3]=spel.stapel.pakKaart();
				
				spel.serverMessage += "<br>Turn: " + spel.sr.tafel[3].getKrt();
				
				syncAll();
				
				
				inzetRonde();
				resetAll();
				
				//deel river
				spel.sr.tafel[4]=spel.stapel.pakKaart();
				
				spel.serverMessage += "<br>River: " + spel.sr.tafel[4].getKrt();
				
				syncAll();
				
				
				inzetRonde();
				
				break;
			}
			
			//wie wint?
			

			int[] hp = new int[6];
			
			i = clients.iterator();
			Vector<Kaart> kaarten = new Vector<Kaart>();
			while(i.hasNext()){
				c = i.next();
				
				kaarten.removeAllElements();
				for(int a = 0; a < spel.sr.tafel.length; a++)
				{
					kaarten.add(spel.sr.tafel[a]);
				}
				
				kaarten.add(c.spel.sr.zoekDeelname(c.deelname.speler.spelerId).kaart.get(0));
				kaarten.add(c.spel.sr.zoekDeelname(c.deelname.speler.spelerId).kaart.get(1));
				spel.sr.zoekDeelname( c.deelname.speler.spelerId).setKaarten( kaarten );
				int[] p = spel.sr.zoekDeelname( c.deelname.speler.spelerId ).getPunten();
				
				if(p[0] == Deelname.ROYAL_FLUSH)
					newWinMessage = "Royal Flush";
				if(p[0] == Deelname.STRAIGHT_FLUSH)
					newWinMessage = "Straight Flush";
				if(p[0] == Deelname.FOUR_OF_A_KIND)
					newWinMessage = "Four of a kind";
				if(p[0] == Deelname.FULL_HOUSE)
					newWinMessage = "Full house";
				if(p[0] == Deelname.FLUSH)
					newWinMessage = "Flush";
				if(p[0] == Deelname.STRAIGHT)
					newWinMessage = "Straight";
				if(p[0] == Deelname.THREE_OF_A_KIND)
					newWinMessage = "Three of a kind";
				if(p[0] == Deelname.TWO_PAIR)
					newWinMessage = "Two pair";
				if(p[0] == Deelname.ONE_PAIR)
					newWinMessage = "One pair";
				if(p[0] == Deelname.HIGH_CARD)
					newWinMessage = "High card";
								
				if(winnaar == null)
				{
					winnaar = c;
					hp = p;
					winMessage = newWinMessage;
					setNewWinnaar(c);
				} else {
					if(p[0] > hp[0])
					{
						setNewWinnaar(c);
					}
					else if (p[0] == hp[0])
					{
						if(p[1] > hp[1])
						{
							setNewWinnaar(c);
						}
						else if(p[1] == hp[1])
						{
							if(p[2] > hp[2])
							{
								setNewWinnaar(c);
							}
							else if(p[2] == hp[2])
							{
								if(p[3] > hp[3])
								{
									setNewWinnaar(c);
								}
								else if(p[3] == hp[3])
								{
									if(p[4] > hp[4])
									{
										setNewWinnaar(c);
									}
									else if(p[4] == hp[4])
									{
										if(p[5] > hp[5])
										{
											setNewWinnaar(c);
										}
										else if(p[5] == hp[5])
										{
											addWinnaar(c);
										}
									}
								}
							}
						}
					}
				}
			}
			
			resetAll();
			
			//
			
			//geef de winnaar(s) hun geld
			double share = spel.sr.inzet / winnaars.size();
			
			//System.out.println("Server: share = " + share);
			
			i = winnaars.iterator();
			while(i.hasNext()){
				c = i.next();
				spel.sr.zoekDeelname(c.speler.spelerId).speler.setSaldo( spel.sr.zoekDeelname(c.speler.spelerId).speler.getSaldo(  ) + share );
				spel.serverMessage += "<br>" + spel.sr.zoekDeelname(c.speler.spelerId).speler.getNaam() + " wins " + share + " Euro with a " + winMessage + "<br>";
			}
			
			i = clients.iterator();
			while(i.hasNext()){
				c = i.next();
				//System.out.println("Server: nieuwSaldo: = " + spel.sr.zoekDeelname(c.speler.spelerId).speler.getSaldo());
			}
			
			i = clients.iterator();
			//verwijder clients die blut zijn
			while(i.hasNext()){
				c = i.next();
				if(spel.sr.zoekDeelname(c.deelname.speler.spelerId).speler.getSaldo() <= Deelname.BIG_BLIND) {
					spel.serverMessage += spel.sr.zoekDeelname(c.deelname.speler.spelerId).speler.getNaam() + " is removed from the game because the player has not enough money.<br>";
					spel.sr.deelnames.remove(c.deelname);
					clients.remove(c);
				}
			}
			
			if(spel.sr.deelnames.size() == 1)
			{
				spel.serverMessage += spel.sr.deelnames.get(0).speler.getNaam() + " has won the game!.<br>";
			}
			
			
			spel.sr.tafel = null;
			syncAll();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {}
			resetAll();
		}
	}
	
	public void setNewWinnaar(ServerConnection c)
	{
		winnaars.removeAllElements();
		winnaar = c;
		winnaars.add(c);
		winMessage = newWinMessage;
	}
	
	public void addWinnaar(ServerConnection c)
	{
		winnaars.add(c);
	}
	
	public void inzetRonde()
	{
		Iterator<ServerConnection> i;
		Iterator<Deelname> g;
		int hInzet = 0;
		boolean inzetChanged = false;
		ServerConnection c;
		Deelname d;
		spel.sr.inzetRonde = 0;
		resetAll();
		
		//zet in (2 inzetrondes)
		int playerCounter = 0;
		for(int counter = 0; counter < 2; counter++)
		{
			playerCounter = 0;
			i = clients.iterator();
			while(i.hasNext())
			{
				playerCounter++;
				c = i.next();
				
				while(spel.sr.zoekDeelname(c.deelname.speler.spelerId).hasfolded == true)
				{
					c = i.next();
				}
				
				spel.sr.zoekDeelname(c.speler.spelerId).verschil = 0;
				g = spel.sr.deelnames.iterator();
				while(g.hasNext())
				{
					d = g.next();
					if(spel.sr.zoekDeelname(c.speler.spelerId) != null)
					{	
						if(spel.sr.zoekDeelname(c.speler.spelerId).inzet < d.inzet)
						{
							if( (d.inzet - spel.sr.zoekDeelname(c.speler.spelerId).inzet) > spel.sr.zoekDeelname(c.speler.spelerId).verschil)
							{
								spel.sr.zoekDeelname(c.speler.spelerId).verschil = d.inzet - spel.sr.zoekDeelname(c.speler.spelerId).inzet;
							}
						}
					}
				}
				
				resetAll();
				
				c.spel = spel;
				try {
					c.up();
				} catch (IOException e) {}
				
				spel.sr.zoekDeelname(c.speler.spelerId).geefBeurt(true);
				c.comment("Jij bent nu aan de beurt");
				c.down();
				spel = c.spel;
				
				spel.serverMessage += "<br>" + spel.sr.zoekDeelname(c.speler.spelerId).speler.getNaam() + " " + spel.sr.lastAction.toLowerCase();
				resetAll();
				syncAll();
				
				g = spel.sr.deelnames.iterator();
				if(playerCounter == spel.sr.deelnames.size() || spel.sr.inzetRonde >= 1)
				{
					while(g.hasNext())
					{
						d = g.next();
						//System.out.println("Server: hInzet = " + hInzet + ", d.inzet = " + d.inzet);
						if(hInzet == 0)
							hInzet = d.inzet;
						else if(hInzet != d.inzet)
						{
							inzetChanged = true;
							break;
						}
					}
					hInzet = 0;
					if(!inzetChanged)
						return;
					inzetChanged = false;
				}
				
				if(spel.sr.actieveSpelers == 1)
				{
					i = clients.iterator();
					while(i.hasNext())
					{
						c = i.next();
						if( !spel.sr.zoekDeelname(c.deelname.speler.spelerId).hasfolded )
						{
							setNewWinnaar(c);
						}
					}
				}
			}
				
			
			spel.sr.inzetRonde++;
			
			resetAll();
		}
		
		// zorg er nu voor dat iedereen evenveel heeft ingezet (oftewel, speler laten callen waar nodig)
		
		
		
		i = clients.iterator();
		while(i.hasNext()){
			c = i.next();
			
			while(spel.sr.zoekDeelname(c.deelname.speler.spelerId).hasfolded == true)
			{
				c = i.next();
			}
			
			spel.sr.zoekDeelname(c.speler.spelerId).verschil = 0;
			g = spel.sr.deelnames.iterator();
			while(g.hasNext())
			{
				d = g.next();
				if(spel.sr.zoekDeelname(c.speler.spelerId).inzet < d.inzet)
				{
					if( (d.inzet - spel.sr.zoekDeelname(c.speler.spelerId).inzet) > spel.sr.zoekDeelname(c.speler.spelerId).verschil)
					{
						spel.sr.zoekDeelname(c.speler.spelerId).verschil = d.inzet - spel.sr.zoekDeelname(c.speler.spelerId).inzet;
					}
				}
			}
			
			resetAll();
			
			c.spel = spel;
			try {
				c.up();
			} catch (IOException e) {}
			spel.sr.zoekDeelname(c.speler.spelerId).geefBeurt(true);
			c.comment("Jij bent nu aan de beurt");
			c.down();
			spel = c.spel;
			
			spel.serverMessage += "<br>" + spel.sr.zoekDeelname(c.speler.spelerId).speler.getNaam() + " " + spel.sr.lastAction.toLowerCase();
			
			syncAll();
			g = spel.sr.deelnames.iterator();
			
			while(g.hasNext())
			{
				d = g.next();
				//System.out.println("Server: hInzet = " + hInzet + " d.inzet = " + d.inzet);
				if(hInzet == 0)
					hInzet = d.inzet;
				else if(hInzet != d.inzet)
				{
					inzetChanged = true;
					break;
				}
			}
			hInzet = 0;
			if(!inzetChanged)
				return;
			inzetChanged = false;
			
			if(spel.sr.actieveSpelers == 1)
			{
				i = clients.iterator();
				while(i.hasNext())
				{
					c = i.next();
					if( !spel.sr.zoekDeelname(c.deelname.speler.spelerId).hasfolded )
					{
						setNewWinnaar(c);
					}
				}
			}
		}
	}
	
	private boolean shouldGameContinue(){
		int levend = 0;
		Iterator<ServerConnection> i = clients.iterator();
		while(i.hasNext()){
			if(i.next().deelname.resultaat == 0){
				levend++;
			}
		}
		return (levend > 1);
	}
	
	public Server(Spel spel, int port){
		clients = new Vector<ServerConnection>();
		this.spel = spel;
		try {
			server = new ServerSocket(port);
			server.setSoTimeout(1000);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public void startGame(){
		////System.out.println("Starting game!");
		openForConnections = false;
	}
	/*
	public void deelKaarten(){
		Iterator<ServerConnection> i = clients.iterator();
		ServerConnection c;
		while(i.hasNext()){
			c = i.next();
			c.deelname.kaart = new Vector<Kaart>();
			c.deelname.kaart.add(spel.stapel.pakKaart());
			c.deelname.kaart.add(spel.stapel.pakKaart());
			c.up();
		}
	}*/
	
	public void waitForAnother(){
		//openForConnections = true;
		try {
			server.setSoTimeout(1000);
		} catch (SocketException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		ServerConnection c = null;
		Object gekregen = null;
		String[] info = new String[2];
		while(openForConnections){
			try {
				Socket verbinding = server.accept();
				c = new ServerConnection(verbinding);
				clients.add(c);
			} catch(InterruptedIOException e){} 
			catch (IOException e) {
				System.err.println("I/O error for the listening connection on 0.0.0.0:" + server.getLocalPort() + ".");
				e.printStackTrace();
			}
		}
		try {
			server.setSoTimeout(0);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public Vector<ServerConnection> getClients(){
		return clients;
	}
	
	
}
